<!DOCTYPE html>
<html>

	<head>
		<meta charset="UTF-8">
		<title>Js 拖拽排序</title>
		<style type="text/css">
			.parent-box {
				width: 500px;
				float: left;
				margin: 40px;
			}
			
			.list {
				width: 100%;
				padding: 10px;
				margin: 0;
				position: relative;
				padding-bottom: 0;
				border: 1px solid black;
			}
			
			.list li {
				display: block;
				width: 500px;
				height: 50px;
				border: 1px solid #999;
				margin-bottom: 10px;
				background: skyblue;
				box-sizing: border-box;
				font-weight: bolder;
				text-align: center;
				line-height: 40px;
				font-size: 20px;
			}
			
			li.edit-able {
				cursor: move;
				border-style: dashed;
				border-color: #eee;
				transition: all .3s ease;
			}
			
			.list li.move-item {
				box-shadow: 4px 4px 4px #AAAAAA;
				opacity: 0.5;
			}
		</style>
	</head>

	<body>
		<h1>拖拽排序</h1>
		<div id="box1" class="parent-box">
			<ul class="list sort_box">
				<li>1</li>
				<li>2</li>
				<li>3</li>
				<li>4</li>
				<li>5</li>
				<li>6</li>
			</ul>
		</div>

		<script type="text/javascript">
			

			function DragDrop(id) {
				this.Box = document.getElementById(id);
				this.list = this.Box.querySelector('.list');
				this.li = this.Box.querySelectorAll('li');
				this.aPosXY = []; //原始位置
				this.aPosXYClone = [];
				this.moveStatus = false; //移动状态
				this.editAble = false; //编辑状态
				this.addBox = null;
				this.moveItem = null;
				this.moveItemH = null;
				this.mouseDownPos = [];
				this.inScope = false;

			}

			DragDrop.prototype.init = function() {
				var that = this;
				// 获取高度
				this.list.style.height = this.li.length * (this.li[0].offsetHeight + parseInt(document.defaultView.getComputedStyle(this.li[0]).marginBottom)) + 'px';

				for(var i = 0; i < this.li.length; i++) {
					var pos = [];
					var posX = this.li[i].offsetLeft; // 获取当前元素相对父级元素的偏移量x
					var posY = this.li[i].offsetTop; //获取当前元素相对父级元素的偏移量y
					pos.x = posX + 'px';
					pos.y = posY + 'px';
					this.aPosXY.push(pos);
					this.li[i].setAttribute('data-index', i)
				}
				//  变为绝对定位
				for(var i in this.aPosXY) {
					this.li[i].style.position = "absolute";
					this.li[i].style.left = this.aPosXY[i].x;
					this.li[i].style.top = this.aPosXY[i].y;
				}

				for(var i = 0; i < this.li.length; i++) {
					this.li[i].onmousedown = function(event, t) {
						that.mouseDown(event, this);
					}
					this.li[i].onmouseup = function() {
						that.moveStatus = false; //关闭可移动状态
						that.mouseUp(that.moveItem);
					}
				}
				window.onmousemove = function(event) {
					if(that.moveStatus) {
						that.mouseMove(event, that.moveItem);
					}
				}
			}

			//鼠标按下
			DragDrop.prototype.mouseDown = function(e, t) {
				var thisIndex = t.getAttribute('data-index');
				//获取当前序号
				this.addBox = document.createElement('div'); // 创建新元素用于存放
				var tWidth = t.offsetWidth + 'px';
				var tHeight = t.offsetHeight + 'px';
				this.addBox.style.width = tWidth;
				this.addBox.style.height = tHeight;
				this.addBox.style.left = this.aPosXY[thisIndex].x;
				this.addBox.style.top = this.aPosXY[thisIndex].y;
				this.list.appendChild(this.addBox);
				this.moveStatus = true;
				this.moveItem = t; //当前移动的元素
				this.mouseDownPos.x = e.pageX - this.list.offsetLeft;
				this.mouseDownPos.y = e.pageY - this.list.offsetTop;
				t.style.zIndex = 100;
				t.classList.add("move-item");
				this.aPosXYClone.splice(0, this.aPosXYClone.length);
				for(var i = 0; i < this.aPosXY.length; i++) { //复制数组
					this.aPosXYClone.push(this.aPosXY[i]);
				}
				t.classList.remove('edit-able');
				console.log(this.mouseDownPos);
			}

			//鼠标移动
			DragDrop.prototype.mouseMove = function(e, obj) {
				var mousetolistX = e.pageX - this.list.offsetLeft; //鼠标相对ul的位置 x
				var mousetolistY = e.pageY - this.list.offsetTop; //鼠标相对ul的位置 y
				var objIndex = obj.getAttribute('data-index'); // 获取当前选中元素的下标
				var objLeft = this.aPosXY[objIndex].x;
				var objTop = this.aPosXY[objIndex].y; //根据下标获取当前选中元素 固定的时候的定位 x,y;
				var relativeObjX = this.mouseDownPos.x - parseInt(objLeft); //鼠标按下时鼠标相对于选中元素的位置x
				var relativeObjY = this.mouseDownPos.y - parseInt(objTop); //鼠标按下时鼠标相对于选中元素的位置y
				var objMoveX = mousetolistX - relativeObjX;
				var objMoveY = mousetolistY - relativeObjY;

				obj.style.left = objMoveX + 'px';
				obj.style.top = objMoveY + 'px';

				for(var i = 0; i < this.aPosXYClone.length; i++) {
					if(!(i == objIndex)) {
						if(objMoveY + obj.offsetHeight >= parseInt(this.aPosXYClone[i].y) + this.li[i].offsetHeight / 2 && objMoveY + obj.offsetHeight < parseInt(this.aPosXYClone[i].y) + this.li[i].offsetHeight || objMoveY >= parseInt(this.aPosXYClone[i].y) && objMoveY < parseInt(this.aPosXYClone[i].y) + this.li[i].offsetHeight / 2) {

							var ts = [];
							ts.x = this.addBox.style.left;
							ts.y = this.addBox.style.top;
							this.aPosXYClone[objIndex] = this.aPosXYClone[i];
							this.aPosXYClone[i] = ts;
							this.addBox.style.left = this.aPosXYClone[objIndex].x;
							this.addBox.style.top = this.aPosXYClone[objIndex].y;
							this.li[i].style.left = ts.x;
							this.li[i].style.top = ts.y;

							return false;
						}
					}
				}

			}

			//鼠标弹起
			DragDrop.prototype.mouseUp = function(t) {
				if(this.moveItem) {
					this.list.removeChild(this.addBox)
					this.moveItem.style.zIndex = null;
					t.classList.remove('move-item');
					this.aPosXY.splice(0, this.aPosXY.length);;
					for(var i = 0; i < this.aPosXYClone.length; i++) { //复制数组
						this.aPosXY.push(this.aPosXYClone[i]);
					}
					t.classList.add('edit-able');
					for(var i in this.aPosXY) {
						this.li[i].style.position = 'absolute';
						this.li[i].style.left = this.aPosXY[i].x;
						this.li[i].style.top = this.aPosXY[i].y;

					}
					this.moveItem = null;
				}
			}
			
			var box1 = new DragDrop('box1');
			box1.init();
			
		</script>
	</body>

</html>